import {compose, withState} from 'recompose'
import Infinite from 'react-infinite'
import React from 'react'
import {
    concat,
    contains,
    equals,
    getDate,
    getDateTime,
    getOptionDisplayValue,
    lensIndex,
    lensProp,
    over,
    path,
    reject,
    set
} from '../util'
import {Box, Button, DatePicker, Input, Popconfirm, Select, Static} from '../components'

const Cell = ({value, rowIndex, onItemClick, action, isHead, cellIndex, isIndex, title = {}, isTitle}) => {
    return (
        <div onClick={() => onItemClick && onItemClick({rowIndex, cellIndex, title, value})}>
            {value}
            <style jsx>{`
                div{
                    width:${title.width || 'auto'};
                    min-width: ${isIndex ? '60px' : '120px'};
                    text-align:${title.textAlign || 'center'};
                    height:${title.height || 'auto'};
                    min-height: 30px;
                    align-items:center;
                    color: rgb(155, 155, 155);
                    line-height:${title.height || '30px'};
                    border:1px solid #ccc;
                    border-left:${isHead ? '1px solid #ccc' : 'none'};
                    border-top:${(isTitle || isHead && isNaN(rowIndex)) ? '1px solid #ccc' : 'none'};
                    background-color:${(isTitle || isHead) ? '#f6f6f6' : (!isTitle && title && title.formatColor) ? title.formatColor(value) : '#fff'};

                    &:hover{
                         background-color:${(isTitle || isHead || action) ? '#f6f6f6' : '#d3d3d3'};
                    }
                }
            `}</style>
        </div>
    )
}

class _Row extends React.Component {
    constructor(props) {
        super(props)
    }


    render() {
        const {state: {row}, setState, onRowSave, showAction, isTitle, onRowEdit, onRowRemove, onItemClick, rowIndex, titles = []} = this.props
        const value = (title) => isTitle ? title.value : title.format ? title.format(row[title.name]) : row[title.name];
        const style = (title, cellIndex) => ({
            width: title.width || '119px',
            border: 'none',
            fontSize: '.875rem',
            lineHeight: '28px',
            borderRadius: '0',
            borderRight: cellIndex == titles.length - 1 ? '1px solid #ccc' : 'none'
        })

        return (
            <Box width='100%' flex='flex' justify='flex-start'>
                <Cell isHead={true}
                      isIndex
                      onItemClick={x => x}
                      rowIndex={rowIndex}
                      value={isNaN(rowIndex + 1) ? '' : rowIndex + 1}
                />
                {titles.map((title, cellIndex) => (
                    <Cell isTitle={isTitle}
                          title={title}
                          key={Math.random()}
                          onItemClick={onItemClick}
                          rowIndex={rowIndex}
                          cellIndex={cellIndex}
                          value={
                              row.edit
                                  ? (title.type == 'select'
                                      ? <Select id={rowIndex + '|' + title.name}
                                                onChange={x => setState({
                                                    row: {
                                                        ...row,
                                                        [title.name]: getOptionDisplayValue(x, title.options || [])
                                                    }
                                                })}
                                                defaultValue={(title.options.find(x => x.displayValue == value(title)))
                                                    ? (title.options.find(x => x.displayValue == value(title))).displayValue
                                                    : ''}
                                                options={title.options || []}
                                                style={style(title, cellIndex)}
                                      />
                                      : ((title.type || '').startsWith('date')
                                              ? <DatePicker
                                                  value={(value(title) != '--') ? new Date(value(title)) : new Date()}
                                                  onChange={x => setState({
                                                      row: {
                                                          ...row,
                                                          [title.name]: title.type.endsWith('ime')
                                                              ? getDateTime(new Date(x))
                                                              : getDate(new Date(x))
                                                      }
                                                  })}
                                                  style={style(title, cellIndex)}
                                                  showTime={title.type.endsWith('ime')}
                                              />
                                              : <Input id={rowIndex + '|' + title.name}
                                                       defaultValue={value(title)}
                                                       style={style(title, cellIndex)}
                                              />
                                      )
                                  )
                                  : value(title)
                          }
                    />
                ))}
                {showAction &&
                <Cell onItemClick={x => x}
                      action
                      isTitle={isTitle}
                      rowIndex={rowIndex}
                      value={
                          isTitle
                              ? '操作'
                              : <Box flex='flex'>
                                  <Static label={row.edit ? '保存' : '编辑'}
                                          onClick={() => {
                                              if (row.edit) {
                                                  let editRow = {}
                                                  titles.map(title => {
                                                      const dom = document.getElementById(rowIndex + '|' + title.name);
                                                      if (dom) {
                                                          editRow[title.name] = dom.value
                                                      }
                                                  })
                                                  onRowSave && onRowSave({rowIndex, row: {...row, ...editRow, edit: false}})
                                                  setState({row: {...row, edit: false}})
                                              } else {
                                                  onRowEdit && onRowEdit({rowIndex})
                                                  setState({row: {...row, edit: true}})
                                              }
                                          }}
                                          color='#35c0c1'
                                          marginRight='1rem'
                                          fontSize='.875rem'
                                  />
                                  <Popconfirm title='确定删除吗?' onConfirm={() => onRowRemove && onRowRemove({rowIndex})}>
                                      <Static label='删除'
                                              color='red'
                                              fontSize='.875rem'
                                      />
                                  </Popconfirm>
                              </Box>
                      }
                />
                }
            </Box>
        )
    }
}

const Row = compose(
    withState('state', 'setState', props => ({
        row: props.row || {}
    }))
)(_Row)

class Grid extends React.Component {
    constructor(prop) {
        super(prop)
    }

    componentWillReceiveProps(nextProps) {
        if (!this.props.state.values && nextProps.values) {
            nextProps.setState({values: nextProps.values})
        }
    }

    render() {
        const {state: {values}, state, setState, showAction, onItemClick, onChange, onAddRow, titles = []} = this.props;
        return (
            <div>
                <Infinite elementHeight={40} useWindowAsScrollContainer>
                    <Box width='100%' height='30px' flex='flex' bgColor='#f6f6f6' justify='flex-start'>
                        {onAddRow && <Button title='新增一行' onClick={onAddRow}/>}
                    </Box>
                    <Row titles={titles} isTitle showAction={showAction}/>
                    {(values || []).map((row, rowIndex) => (
                        <Row onItemClick={onItemClick}
                             showAction={showAction}
                             key={Math.random()}
                             onRowEdit={({rowIndex}) => {
                                 const v = set(
                                     lensIndex(rowIndex),
                                     set(lensProp('edit'), true, values[rowIndex]),
                                     values
                                 )
                                 setState({values: v})
                             }}
                             onAddRow={() => {
                                 onChange && onChange(concat([{edit: true}], values))
                                 setState({...state, resumes: concat([{edit: true}], values)})
                             }}
                             onRowSave={({rowIndex, row}) => {
                                 const newValues = set(lensIndex(rowIndex), row, values)
                                 setState({values: newValues})
                                 onChange && onChange(newValues)
                             }}
                             onRowRemove={({rowIndex}) => {
                                 const newValues = values.filter((x, i) => i != rowIndex)
                                 setState({values: newValues})
                                 onChange && onChange(newValues)
                             }}
                             titles={titles}
                             row={row}
                             rowIndex={rowIndex}
                        />
                    ))}
                </Infinite>
            </div>
        )
    }
}

export default compose(
    withState('state', 'setState', props => ({
        values: null
    }))
)(Grid)